<template>
  <div class="scroll-image-wrapper" @mouseenter="expand" @mouseleave="collapse">
    <div v-if="!isExpanded" class="ad-text-only">
      <div class="scroll-bg-css"></div>
      <div class="ad-text-on-bg">
        <span v-for="(char, idx) in adTextArr" :key="idx">{{ char }}</span>
      </div>
    </div>
    <transition name="scroll-roll">
      <div v-show="isExpanded && !imgError" class="scroll-body" :class="{ 'rolling': isRolling }">
        <div class="scroll-head-css scroll-head-left-css"></div>
        <div class="main-image-roller" :style="rollerStyle">
          <img :src="image" alt="动态图片" class="main-image" @error="onImgError" @load="onImgLoad" />
        </div>
        <div class="scroll-head-css scroll-head-right-css"></div>
      </div>
    </transition>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, watch } from 'vue'
const props = defineProps({
  image: { type: String, required: true }
})
const isExpanded = ref(false)
const imgError = ref(false)
const imgNaturalHeight = ref(0)
const imgNaturalWidth = ref(0)
const windowWidth = ref(window.innerWidth)
const rollerWidth = ref(0)
const isRolling = ref(false)

function expand() {
  isExpanded.value = true
  isRolling.value = true
  // 动画：宽度从0到目标宽度
  const target = Math.floor(windowWidth.value / 3)
  rollerWidth.value = 0
  let start: number | null = null
  function animate(ts: number) {
    if (!start) start = ts
    const progress = Math.min((ts - start!) / 700, 1)
    rollerWidth.value = Math.floor(target * progress)
    if (progress < 1) {
      requestAnimationFrame(animate)
    } else {
      rollerWidth.value = target
      isRolling.value = false
    }
  }
  requestAnimationFrame(animate)
}
function collapse() {
  isRolling.value = true
  // 动画：宽度从当前到0
  const startWidth = rollerWidth.value
  let start: number | null = null
  function animate(ts: number) {
    if (!start) start = ts
    const progress = Math.min((ts - start!) / 500, 1)
    rollerWidth.value = Math.floor(startWidth * (1 - progress))
    if (progress < 1) {
      requestAnimationFrame(animate)
    } else {
      rollerWidth.value = 0
      isExpanded.value = false
      isRolling.value = false
    }
  }
  requestAnimationFrame(animate)
}
const adText = '广告位招租'
const adTextArr = computed(() => adText.split(''))
function onImgError() { imgError.value = true }
function onImgLoad(e: Event) {
  imgError.value = false
  const target = e.target as HTMLImageElement
  if (target) {
    imgNaturalWidth.value = target.naturalWidth
    imgNaturalHeight.value = target.naturalHeight
  }
}
function updateWindowWidth() {
  windowWidth.value = window.innerWidth
}
onMounted(() => {
  window.addEventListener('resize', updateWindowWidth)
})
const mainImageStyle = computed(() => {
  let height = 'auto'
  if (imgNaturalWidth.value && imgNaturalHeight.value && rollerWidth.value) {
    height = `${Math.round(imgNaturalHeight.value * rollerWidth.value / imgNaturalWidth.value)}px`
  }
  return {
    width: rollerWidth.value + 'px',
    height,
    objectFit: 'contain' as const,
    borderRadius: '0 24px 24px 0',
    boxShadow: '0 2px 12px #f7e9c1',
    zIndex: 1,
    transition: isRolling.value ? 'width 0.7s cubic-bezier(.6,1.5,.5,1), height 0.7s cubic-bezier(.6,1.5,.5,1)' : ''
  }
})
const rollerStyle = computed(() => ({
  width: rollerWidth.value + 'px',
  overflow: 'hidden',
  transition: isRolling.value ? 'width 0.7s cubic-bezier(.6,1.5,.5,1)' : ''
}))
</script>

<style scoped>
.scroll-image-wrapper {
  display: flex;
  align-items: flex-start;
  cursor: pointer;
  min-width: 40px;
  position: relative;
  height: 180px;
}
.ad-text-only {
  width: 40px;
  height: 180px;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}
.scroll-bg-css {
  width: 40px;
  height: 180px;
  border-radius: 24px;
  background: linear-gradient(135deg, #f7e9c1 60%, #eab308 100%);
  box-shadow: 0 2px 12px #f7e9c1, 0 0 0 4px #fffbe6 inset;
  position: absolute;
  left: 0;
  top: 0;
  z-index: 1;
}
.ad-text-on-bg {
  position: absolute;
  left: 0;
  top: 0;
  width: 40px;
  height: 180px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  font-size: 22px;
  color: #eab308;
  font-weight: bold;
  letter-spacing: 2px;
  pointer-events: none;
  user-select: none;
  text-shadow: 0 2px 8px #fffbe6, 0 1px 2px #bfae6a;
  z-index: 2;
}
.ad-text-on-bg span {
  line-height: 1.2;
  margin: 0 2px;
}
.scroll-body {
  background: #fffbe6;
  border-radius: 0 24px 24px 0;
  box-shadow: 0 4px 24px 0 rgba(180,160,80,0.10);
  overflow: visible;
  margin-left: -8px;
  display: flex;
  align-items: center;
  animation: scrollIn 0.7s cubic-bezier(.6,1.5,.5,1) forwards;
  position: relative;
  min-height: 60px;
  padding-right: 0;
}
.scroll-head-css {
  width: 40px;
  min-width: 40px;
  border-radius: 24px;
  background: linear-gradient(135deg, #f7e9c1 60%, #eab308 100%);
  box-shadow: 0 2px 12px #f7e9c1, 0 0 0 4px #fffbe6 inset;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: height 0.7s cubic-bezier(.6,1.5,.5,1);
}
.scroll-head-left-css {
  margin-right: -8px;
}
.scroll-head-right-css {
  margin-left: 0;
}
.main-image-roller {
  display: flex;
  align-items: center;
  overflow: hidden;
  height: 100%;
}
.main-image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  border-radius: 0 24px 24px 0;
  box-shadow: 0 2px 12px #f7e9c1;
  z-index: 1;
  transition: width 0.7s cubic-bezier(.6,1.5,.5,1), height 0.7s cubic-bezier(.6,1.5,.5,1);
}
/* 动画 */
.scroll-roll-enter-active, .scroll-roll-leave-active {
  transition: opacity 0.5s;
}
.scroll-roll-enter-from, .scroll-roll-leave-to {
  opacity: 0;
}
.scroll-roll-enter-to, .scroll-roll-leave-from {
  opacity: 1;
}
@keyframes scrollIn {
  from { width: 0; opacity: 0; }
  to { width: 100%; opacity: 1; }
}
</style> 